package com.mallcloud.mall.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mallcloud.mall.product.api.dto.AttrExtendDTO;
import com.mallcloud.mall.product.api.dto.AttrOptionDTO;
import com.mallcloud.mall.product.api.dto.SkuPublishDTO;
import com.mallcloud.mall.product.api.entity.SkuStockModel;
import com.mallcloud.mall.product.api.entity.SpuSkuAttrValueModel;
import com.mallcloud.mall.product.api.vo.*;
import com.mallcloud.mall.common.core.constant.CacheConstants;
import com.mallcloud.mall.converter.SkuConverter;
import com.mallcloud.mall.product.api.entity.SkuModel;
import com.mallcloud.mall.product.mapper.AttrMapper;
import com.mallcloud.mall.product.mapper.SkuMapper;
import com.mallcloud.mall.product.service.*;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * sku信息
 */
@Service
@AllArgsConstructor
public class SkuServiceImpl extends ServiceImpl<SkuMapper, SkuModel> implements SkuService {
    private final SkuConverter skuConverter;
    private final SkuStockService skuStockService;
    private final AttrMapper attrMapper;
    private final SpuSkuAttrValueService spuSkuAttrValueService;

    // App服务------------
    @Override
    @Cacheable(cacheNames = CacheConstants.SKU_OF_SPU_DETAIL_KEY, key = "#spuId", sync = true)
    public List<AppSkuVO> getSkuBySpuId(Long spuId) {
        String attrUnionAttrValue = ":";
        String attrUnionAttr = ";";
        List<AppSkuVO> skuAppList = new ArrayList<>();
        List<SkuExAttrVO> skuData = this.baseMapper.getSkuBySpuId(spuId);
        for (SkuExAttrVO sku : skuData) {
            AppSkuVO skuAppVO = skuConverter.VOToVO(sku);
            String properties = "";
            for (SpuSkuAttrValueVO spuSkuAttrValue : sku.getSpuSkuAttrValues()) {
                properties = properties + spuSkuAttrValue.getAttrName() + attrUnionAttrValue + spuSkuAttrValue.getAttrValueName() + attrUnionAttr;
            }
            skuAppVO.setProperties(properties.substring(0, properties.length() - 1));
            skuAppList.add(skuAppVO);
        }
        return skuAppList;
    }

    // 后台服务------------
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean saveSku(SkuVO dto) {
        SkuModel sku = skuConverter.VOtoModel(dto);

        sku.setPriceFee(sku.getPriceFee().multiply(BigDecimal.valueOf(100)));
        sku.setMarketPriceFee(sku.getMarketPriceFee().multiply(BigDecimal.valueOf(100)));

        this.save(sku);
        Long skuId = sku.getSkuId();

        SkuStockModel skuStock = skuConverter.toSkuStock(dto);
        skuStock.setSkuId(skuId);
        skuStock.setLockStock(0);
        return skuStockService.save(skuStock);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateSku(SkuVO dto) {
        SkuModel sku = skuConverter.VOtoModel(dto);

        sku.setPriceFee(sku.getPriceFee().multiply(BigDecimal.valueOf(100)));
        sku.setMarketPriceFee(sku.getMarketPriceFee().multiply(BigDecimal.valueOf(100)));

        this.updateById(sku);
        Long skuId = sku.getSkuId();

        return skuStockService.update(Wrappers.<SkuStockModel>lambdaUpdate()
                .eq(SkuStockModel::getSkuId, skuId)
                .set(SkuStockModel::getStock, dto.getStock())
                .set(SkuStockModel::getActualStock, dto.getActualStock())
                .set(SkuStockModel::getLockStock, dto.getLockStock())
        );
    }

    @Override
    public IPage<SkuVO> pageSku(Page page, SkuModel dto) {
        IPage<SkuVO> pageSku = this.baseMapper.pageSku(page, dto);
        pageSku.getRecords().forEach(x -> {
            x.setPriceFee(x.getPriceFee().divide(BigDecimal.valueOf(100), 2));
            x.setMarketPriceFee(x.getMarketPriceFee().divide(BigDecimal.valueOf(100), 2));
        });
        return pageSku;
    }

    @Override
    public SkuVO getSku(Long skuId) {
        SkuVO sku = this.baseMapper.getSku(skuId);
        sku.setPriceFee(sku.getPriceFee().divide(BigDecimal.valueOf(100), 2));
        sku.setMarketPriceFee(sku.getMarketPriceFee().divide(BigDecimal.valueOf(100), 2));
        return sku;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean saveSkuPublish(Long spuId, String spuName, List<SkuPublishDTO> skuPublishList) {
        skuPublishList.forEach(x -> {
            x.setSpuId(spuId);
            x.setStatus(Boolean.TRUE);
        });
        List<SkuModel> skuList = skuConverter.DTOToModel(skuPublishList);

        // 查询全部attr属性对象
        List<AttrExtendVO> attrExtends = attrExtendListBySkuPublish(skuPublishList);

        // 循环保存sku 并保存关联spuSkuAttr属性
        for (int i = 0; i < skuList.size(); i++) {
            SkuModel sku = skuList.get(i);
            SkuPublishDTO skuPublish = skuPublishList.get(i);
            List<AttrOptionDTO> attrOptionList = skuPublish.getAttrOptionList();

            // 元转分
            sku.setPriceFee(sku.getPriceFee().multiply(BigDecimal.valueOf(100)));
            sku.setMarketPriceFee(sku.getMarketPriceFee().multiply(BigDecimal.valueOf(100)));

            // 保存sku
            List<String> attrList = new ArrayList<>(attrOptionList.size());
            List<String> attrNameList = new ArrayList<>(attrOptionList.size());
            for (AttrOptionDTO attrOption : attrOptionList) {
                attrList.add(String.valueOf(attrOption.getId()));
                attrNameList.add(attrOption.getName());
            }
            sku.setAttrs(String.join(StrUtil.COMMA, attrList));
            sku.setSkuName(String.format("%s[%s]", spuName, String.join(StrUtil.COLON, attrNameList)));
            this.save(sku);
            Long skuId = sku.getSkuId();

            // 保存库存信息
            SkuStockModel skuStock = new SkuStockModel();
            skuStock.setSkuId(skuId);
            skuStock.setActualStock(skuPublish.getStock());
            skuStock.setStock(skuPublish.getStock());
            skuStock.setLockStock(0);
            skuStockService.save(skuStock);

            // 保存spuSkuAttr属性
            List<SpuSkuAttrValueModel> spuSkuAttrValueList = attrExtends.stream()
                    // 从attrExtends中过滤出当前sku对应的spuSkuAttr属性
                    .filter(x -> {
                        for (AttrOptionDTO dto : attrOptionList) {
                            if (x.getAttrValueId().equals(dto.getId())) {
                                return true;
                            }
                        }
                        return false;
                    })
                    .map(x -> {
                        SpuSkuAttrValueModel m = skuConverter.VOToModel(x);
                        m.setSpuId(spuId);
                        m.setSkuId(skuId);
                        m.setStatus(true);
                        return m;
                    })
                    .collect(Collectors.toList());
            spuSkuAttrValueList.forEach(spuSkuAttrValueService::save);
        }
        return Boolean.TRUE;
    }

    /**
     * 查询发布商品sku属性值
     *
     * @param skuList
     * @return
     */
    private List<AttrExtendVO> attrExtendListBySkuPublish(List<SkuPublishDTO> skuList) {
        List<AttrExtendDTO> attrExtendDTOList = new ArrayList<>();
        for (SkuPublishDTO dto : skuList) {
            attrExtendDTOList.addAll(
                    dto.getAttrOptionList().stream()
                            .map(x -> new AttrExtendDTO(x.getParentId(), x.getId())).collect(Collectors.toList())
            );
        }
        return attrMapper.extendAttr(attrExtendDTOList);
    }
}
